#pragma once

#include <AVUIFrameworkElement.h>

namespace AVUI {

class TextBlock;
class DataTemplate;
class DataTemplateSelector;

class ContentPresenter : public FrameworkElement
{
    friend class ItemsControl;
public:
    ContentPresenter();
    ~ContentPresenter();

    DECLARE_ELEMENT(ContentPresenter, FrameworkElement);

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(Content);
        DECLARE_ATTRIBUTE_CONTENTPROPERTY();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<Object> get_Content() { return GetValue(get_ContentProperty()); }
    void set_Content(Object* pValue) { return SetValue(get_ContentProperty(), pValue); }

    DECLARE_DEPENDENCY_PROPERTY(ContentTemplate);
    TRefCountedPtr<DataTemplate> get_ContentTemplate() { return (DataTemplate*)(Object*)GetValue(get_ContentTemplateProperty()); }
    void set_ContentTemplate(DataTemplate* pValue) { SetValue(get_ContentTemplateProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY(ContentTemplateSelector);
    TRefCountedPtr<DataTemplateSelector> get_ContentTemplateSelector() { return (DataTemplateSelector*)(Object*)GetValue(get_ContentTemplateSelectorProperty()); }
    void set_ContentTemplateSelector(DataTemplateSelector* pValue) { SetValue(get_ContentTemplateSelectorProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY(ContentSource);
    TRefCountedPtr<String> get_ContentSource() { return (String*)(Object*)GetValue(get_ContentSourceProperty()); }
    void set_ContentSource(String* pValue) { SetValue(get_ContentSourceProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY(ContentStringFormat);
    TRefCountedPtr<String> get_ContentStringFormat() { return (String*)(Object*)GetValue(get_ContentStringFormatProperty()); }
    void set_ContentStringFormat(String* pValue) { SetValue(get_ContentStringFormatProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY(Template);
    TRefCountedPtr<DataTemplate> get_Template() { return (DataTemplate*)(Object*)GetValue(get_TemplateProperty()); }
    void set_Template(DataTemplate* pValue) { SetValue(get_TemplateProperty(), (Object*)pValue); } 

    virtual int get_VisualChildrenCount();
    virtual Visual* GetVisualChild(int);

    bool get_TemplateIsCurrent() { return m_templateIsCurrent; }

    virtual void EndInit();

protected:

    virtual Size MeasureOverride(const Size& constraintSize);
    virtual Size ArrangeOverride(const Size& constraintSize);

    virtual FrameworkTemplate* get_TemplateInternal() { return (FrameworkTemplate*) (DataTemplate*)get_Template(); }
    virtual void OnPreApplyTemplate();
    virtual void OnTemplatedParentSet();

    virtual TRefCountedPtr<DataTemplate> ChooseTemplate();

    void BindProperty(DependencyObject* pFrom, DependencyProperty* pDPFrom, DependencyObject* pTo, DependencyProperty* pDPTo);

private:
    static void StaticConstructor();

    void EnsureTemplate();
    void RemoveCachedChild();
    static void OnContentChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
    static void OnContentTemplateChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
    static void OnContentTemplateSelectorChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);
    static void OnTemplateChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* e);

    void PrepareContentPresenter(Object* pItem, DataTemplate* pItemTemplate, DataTemplateSelector* pItemTemplateSelector);
    void AutoAliasContentPresenter(String* pContentSource);


    TWeakPtr<UIElement> m_pCachedChild;
    TRefCountedPtr<TextBlock> m_pTextPresenter;
    bool m_contentIsItem : 1;
    bool m_templateIsCurrent : 1;

};


}; // namespace AVUI

